<template>
  <section class="query-form">
    <section ref="formContentConRef" class="form-content-con">
      <a-form :model="form" layout="inline">
        <a-form-item
          v-for="(item, index) in renderFormItem"
          v-show="index < showFormItemNum || showMore"
          :key="item.field"
          :field="item.field"
          :label="item.label"
          v-bind="item.formItemProps || {}"
          show-colon
        >
          <component
            :is="item.component"
            v-model="form[item.field]"
            v-bind="item.componentProps"
            v-model:is-reset="isReset"
          />
        </a-form-item>
      </a-form>
    </section>
    <section class="right-con">
      <div class="right-con-btns">
        <a-button type="primary" @click="queryHandle">查询</a-button>
        <a-button @click="resetHandle">重置</a-button>
        <a-button
          v-if="renderFormItem.length > showFormItemNum"
          class="more-btn"
          type="text"
          @click="setShowMore"
          >{{ showMore ? '收起' : '展开' }}
          <icon-double-down v-show="!showMore" />
          <icon-double-up v-show="showMore" />
        </a-button>
      </div>
    </section>
  </section>
</template>

<script setup lang="ts">
  import {
    ref,
    defineProps,
    PropType,
    defineAsyncComponent,
    shallowRef,
    watch,
    onMounted,
  } from 'vue';
  import lodash from 'lodash';
  import {
    ComponentCfg,
    createDefaultComponents,
  } from '@/common/components/query-form/config';

  interface AnyObject {
    [key: string]: any;
  }

  interface RenderKeyItem {
    key: string;
    value: any;
    componentProps: AnyObject;
  }

  type StringOrObj = string | RenderKeyItem;

  type RenderKeys = StringOrObj[];

  const props = defineProps({
    componentConfig: {
      type: Object,
      default: () => ({}),
    },
    renderConfig: {
      type: Object,
      default: () => ({}),
    },
    renderKeys: {
      type: Array as PropType<RenderKeys>,
      default: () => [],
    },
    hasEmptyValue: {
      type: Boolean,
      default: true,
    },
  });
  const emit = defineEmits(['search', 'reset']);
  const form = ref<object>({});
  const showMore = ref(false);
  const formContentConRef = ref();
  const showFormItemNum = ref(3);
  const defaultForm: any = {};
  const isReset = ref(false);
  const renderFormItem = ref<any[]>([]); // 最终渲染的组件
  const componentCfg: ComponentCfg = {
    // 所有组件
    ...createDefaultComponents(),
    ...props.componentConfig,
  };

  watch(
    () => props.renderKeys,
    () => {
      initRender();
    }
  );

  const initRender = () => {
    const renderList: any[] = [];
    const { renderConfig } = props;

    console.log('renderConfig', renderConfig);

    props.renderKeys.forEach((item) => {
      let targetItem: RenderKeyItem = {
        key: '',
        value: '',
        componentProps: {},
      };

      if (typeof item === 'string') {
        targetItem.key = item;
      } else {
        targetItem = item;
      }
      console.log('targetItem', targetItem);

      const targetCfg: any = renderConfig[targetItem.key];

      console.log('targetCfg', targetCfg);

      if (targetCfg && componentCfg[targetCfg.componentName]) {
        renderList.push({
          ...targetCfg,
          componentProps: {
            ...(targetCfg.componentProps || {}),
            ...(targetItem.componentProps || {}),
          },
          component: shallowRef(
            defineAsyncComponent(componentCfg[targetCfg.componentName])
          ),
        });
        defaultForm[targetCfg.field] = targetCfg.value || targetItem.value;
      }
    });

    renderFormItem.value = renderList;
    form.value = lodash.cloneDeep(defaultForm);
  };
  onMounted(() => {
    const num = formContentConRef.value.clientWidth / 300;
    showFormItemNum.value = Math.floor(num);
  });
  initRender();

  const queryHandle = () => {
    emit('search', getStatus());
  };

  const setShowMore = () => {
    showMore.value = !showMore.value;
  };

  const resetHandle = () => {
    form.value = lodash.cloneDeep(defaultForm);
    isReset.value = true;
    emit('reset', getStatus());
  };

  const filterEmptyValueHandle = (data: AnyObject) => {
    const keys = Object.keys(data);
    const emptyValue: any[] = [undefined, ''];

    keys.forEach((key) => {
      if (emptyValue.includes(data[key])) {
        delete data[key];
      }
    });
  };

  const reset = () => {
    form.value = lodash.cloneDeep(defaultForm);
  };

  const getStatus = () => {
    const resData = lodash.cloneDeep(form.value);

    if (props.hasEmptyValue) {
      filterEmptyValueHandle(resData);
    }
    return format(resData);
  };
  const format = (resData) => {
    // 特殊处理"dateRangPicker"
    renderFormItem.value.forEach((item) => {
      if (item.componentName === 'dateRangPicker') {
        let defaultKey = ['startDate', 'endDate'];
        let defaultTime = ['00:00:00', '23:59:59'];
        const hasValueKey = item.componentProps?.valueKey;
        if (hasValueKey && item.componentProps.valueKey.length) {
          defaultKey = item.componentProps.valueKey;
        }
        if (hasValueKey && item.componentProps.defaultTime?.length) {
          defaultTime = item.componentProps.defaultTime;
        }
        if (resData[item.field] && resData[item.field]?.length) {
          defaultKey.forEach((key, index) => {
            resData[key] = `${resData[item.field][index]} ${
              defaultTime[index]
            }`;
          });
          delete resData[item.field];
        }
      }
    });
    return resData;
  };

  defineExpose({ getStatus, reset });
</script>

<style lang="less" scoped>
  .query-form {
    display: flex;
    width: 100%;
    padding: 16px;
    background: #f7f9fc;
    border-radius: 8px;
    padding-bottom: 0;
    :deep(.arco-form-item) {
      margin-right: 16px;
      margin-bottom: 16px;
    }
  }

  .form-content-con {
    flex: 1;
    width: 1px;
  }

  :deep(.arco-form-item) {
    width: 290px !important;
    height: 32px;
    background: #fff;
    border: 1px solid #d9dee7;
    border-radius: 3px;
    .arco-form-item-content {
      height: 32px;
    }

    &:focus-within {
      border-color: #165dff;
    }

    .arco-form-item-label-col {
      padding-left: 12px;
    }

    .arco-input-wrapper,
    .arco-picker,
    .arco-select-view-single {
      padding-left: 0;
      background-color: unset !important;
      border-color: transparent;
    }
    .arco-input-append {
      border: none;
      height: 30px;
      background: #fff;
    }
  }
  .right-con {
    .right-con-btns {
      :deep(.arco-btn) {
        margin-right: 8px;
      }
      .more-btn {
        padding-right: 0;
        padding-left: 0;
        margin-right: 0;
        margin-left: 8px;
      }
    }
  }
</style>
